<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>后期处理通道增强图像效果-探照灯效果</title>
    <style>
        canvas{
            border:1px solid #ccc;
        }
    </style>
</head>
<body>
    <canvas width="554" height="554"></canvas>

    <script src="/common/lib/gl-renderer.js"></script>

    <script type="module">
        import { grayMatrix } from "/review/common/lib/utils.js"

        /**
         * 1.创建renderer对象
         * 2.创建webgl程序
         * 3.创建uniform变量
         * 4.将数据存入缓冲区
         * 5.渲染
         * */ 

        //  1.
        const canvas = document.querySelector("canvas");
        const renderer = new GlRenderer(canvas);

        (async function(){
            // 2.
            const vertex = `
                attribute vec2 a_vertexPosition;
                attribute vec2 uv;
                varying vec2 vUv;

                void main(){
                    vUv = uv;
                    gl_Position = vec4(a_vertexPosition, 1.0, 1.0);
                }
            `;
            const fragment = `
                #ifdef GL_ES
                precision highp float;
                #endif

                uniform sampler2D tMap;
                uniform vec2 uMouse;

                varying vec2 vUv;

                vec3 hsv2rgb(vec3 c){
                    vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0), 6.0)-3.0)-1.0, 0.0, 1.0);
                    rgb = rgb * rgb * (3.0 - 2.0 * rgb);
                    return c.z * mix(vec3(1.0), rgb, c.y);
                }

                // 二维随机数
                float random(vec2 st){
                    return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);
                }
                // 二维噪声
                float noise(vec2 st){
                    vec2 i = floor(st);
                    vec2 f = fract(st);
                    f = smoothstep(0.0, 1.0, f);
                    // 对x、y方向分别做线性插值
                    return mix(
                        mix(random(i + vec2(0.0,0.0)), random(i + vec2(1.0,0.0)), f.x), 
                        mix(random(i + vec2(0.0,1.0)), random(i + vec2(1.0,1.0)), f.x), 
                        f.y);
                }

                void main() {
                    vec2 st = vUv * 10.0;

                    vec2 fr = fract(st);
                    vec2 fl = floor(st);

                    vec3 color = vec3(0.0);
                    color += step(0.08, fr.x)*step(fr.x, 0.92) * step(0.08, fr.y)*step(fr.y, 0.92);
                    float r = noise(fl);

                    gl_FragColor.rgb = hsv2rgb(color * r * 3.0 + 0.05);
                    gl_FragColor.a = 1.0;
                }
            `;
            const lightFragment = `
                #ifdef GL_ES
                precision highp float;
                #endif

                uniform sampler2D tMap;
                uniform vec2 uMouse;

                varying vec2 vUv;

                vec3 rgb2hsv(vec3 c){
                    vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
                    vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
                    vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
                    float d = q.x - min(q.w, q.y);
                    float e = 1.0e-10;
                    return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
                }

                void main() {
                    vec2 uv = vUv;
                    vec3 color = texture2D(tMap, uv).rgb;

                    float d = length(uv - uMouse);
                    d = 1.0 - smoothstep(0.195, 0.2, d);
                    
                    if(rgb2hsv(color).y * rgb2hsv(color).z > 0.005){
                        color *= d;
                    }

                    gl_FragColor.rgb = color;
                    gl_FragColor.a = 1.0;
                }
            `;
            

            const program = renderer.compileSync(fragment,vertex);
            renderer.useProgram(program);

            // 3.
            renderer.uniforms.uMouse = [0.0, 0.0];
            // 4.
            renderer.setMeshData([{
                positions:[
                    [-1, -1],
                    [-1, 1],
                    [1, 1],
                    [1, -1],
                ],
                attributes:{
                    uv:[
                        [0, 0],
                        [0, 1],
                        [1, 1],
                        [1, 0],
                    ]
                },
                cells: [[0, 1, 2], [2, 0, 3]],
            }]);

            // 5.
            // renderer.render();

            let fbo1 = renderer.createFBO();
            function update(){

                renderer.bindFBO(fbo1);//绑定帧缓冲对象
                renderer.render();//渲染到帧缓冲对象上

                // 输出到画布
                const lightProgram = renderer.compileSync(lightFragment,vertex);
                renderer.useProgram(lightProgram);
                renderer.setMeshData(program.meshData);
                renderer.uniforms.tMap = fbo1.texture;
                renderer.bindFBO(null);
                renderer.render();
                
            }   
            update();

            canvas.addEventListener("mousemove",function(e){
                const { left, top } = canvas.getBoundingClientRect();
                const offsetX = e.x - left;
                const offsetY = e.y - left;
                renderer.uniforms.uMouse = [offsetX / canvas.width, 1.0 - offsetY / canvas.height];
            });

        })();
        
    </script>
</body>
</html>